#include "StdAfx.h"
#include "RetrySender.h"
#include "SimpleLogger.h"

namespace RoomFW {

RetrySender::RetrySender(ActiveObject* parent) :
	//
	// Initialize Base class.
	//
	ActiveObject::MessageHandler(parent),
	//
	// Initialize attributes.
	//
	map_()
{
}

void RetrySender::delaySend(int32_t timeout, const PortIndex& portIndex, MessageID messageID, IPayloadSP payload)
{
	TimeValue tv;
	tv.setMilliseconds(timeout);
	this->delaySend(tv, portIndex, messageID, payload);
}

void RetrySender::delaySend(const TimeValue& timeout, const PortIndex& portIndex, MessageID messageID, IPayloadSP payload)
{
	RoomTimer::TimerId tid = this->setTimer(timeout);
	map_[tid] = RoomMessageSP(new RoomMessage(portIndex, messageID, payload));
}

bool RetrySender::handle(RoomMessageSP message)
{
	//
	// Set return value to true to indicate that message has been handled.
	//
	bool retVal = false;

	//
	// Catch all exceptions here.  Any that escape will result in the thread exiting.
	//
	try
	{
		//
		// Only handling specific timer messages.
		//
		if (message->portIndex().port() == this->getTimerPort())
		{
			TimerMessageMap::iterator i = map_.find(message->messageID());
			if (map_.end() != i)
			{
				retVal = true;
				RoomMessageSP message = i->second;
				map_.erase(i);
				this->sendMessage(message->portIndex(), message->messageID(), IPayload::ReleaseOwnership(message->releasePayload()));
			}
		}
	}
	//
	// For now, this class catches exceptions and logs them.  If a specific client wants to be
	// notified of errors, then that can be added.
	//
	catch (ErrorHandling::IError& e)
	{
		e.setSourceObjectName(this->getObjectName());
		G_LOG_0_ERROR(e.what());
		ASSERT(false);
	}
	catch (std::exception& e)
	{
		G_LOG_2_ERROR("%s: %s", this->getObjectName(), e.what());
		ASSERT(false);
	}
	catch (...) // You must enable SEH exceptions to catch hardware (e.g. memory access) errors.
	{
		G_LOG_1_ERROR("%s: Unhandled Exception", this->getObjectName());
		ASSERT(false);
	}
	return retVal;
}

} // End namespace
